<!-- 富文本组件 -->
<template>
  <div class="tinymceEditor">
    <textarea id="tinymceEditor"></textarea>

    <!-- 图片上传弹窗 -->
    <el-dialog
			title="图片上传"
			class="uploadPic"
			width="700px"
			center 
      draggable
      v-model="showPic"
			:append-to-body="false"
			:close-on-click-modal="false"
			:close-on-press-escape="false"
			@close="doClosePic">
			<el-tabs v-model="insertType" type="border-card">
				<el-tab-pane name="1" label="插入图片">
					<el-form :model="form" :rules="rules" ref="formRef" label-width="80px">
						<el-form-item label="地址：" prop="src">
							<el-input v-model="form.src" placeholder="请输入图片地址" clearable style="width: 100%;"></el-input>
						</el-form-item>
					</el-form>
				</el-tab-pane>
				<el-tab-pane name="2" label="本地上传">
					<div class="upload_pic_btn_box">
						<div>已上传 <span class="upload_pic_number">{{dataList.length}}</span> 张图片</div>
						<el-upload
							v-show="dataList.length > 0"
							action=""
							multiple
							accept="image/*"
							:show-file-list="false"
							:before-upload="beforeUploadPic"
							:http-request="doUploadFilePic">
							<el-button size="small" icon="Plus" class="upload_pic_btn_style">选择图片上传</el-button>
						</el-upload>
					</div>
					<div v-show="dataList.length === 0" class="upload_pic_tips_box">
						<el-upload
							action=""
							multiple
							accept="image/*"
							:show-file-list="false"
							:before-upload="beforeUploadPic"
							:http-request="doUploadFilePic">
              <div class="upload_pic_tips">
                <svg t="1608715286589" class="icon" viewBox="0 0 1128 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7826" width="74" height="74"><path d="M165.789 99.167h783c22.5 0 40.5 18 40.5 40.5v319.5c-40.5-31.5-117-81-175.5-81-85.5 0-162 198-256.5 198-72-4.5-171-85.5-283.5-72-45 9-108 81-148.5 135v-499.5c0-22.5 18-40.5 40.5-40.5zM354.788 423.167c-36 0-67.5-13.5-90-36s-36-58.5-36-90c0-31.5 13.5-67.5 36-90 22.5-22.5 54-36 90-36 31.5 0 63 13.5 90 36 22.5 22.5 36 58.5 36 90 0 31.5-13.5 67.5-36 90-27 22.5-58.5 36-90 36zM971.288 40.667h-828c-45 0-81 36-81 81v738c0 45 36 81 81 81h828c45 0 81-36 81-81v-738c0-45-36-81-81-81z" p-id="7827" fill="#DFDFDF"></path></svg>
                <el-button size="small" class="upload_pic_btn_style">可选择多张图片同时上传</el-button>
              </div>
						</el-upload>
					</div>
					<div v-show="dataList.length > 0" class="upload_pic_imgs">
						<div v-for="(d, index) in dataList" :key="index">
							<el-image :src="d.src" fit="fill" style="width: 100%; height: 100%"></el-image>
							<svg @click="dataList.splice(index, 1)" t="1608718992636" class="icon upload_pic_delete" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="29470" width="20" height="20"><path d="M0 0h804.571429a219.428571 219.428571 0 0 1 219.428571 219.428571v804.571429H219.428571a219.428571 219.428571 0 0 1-219.428571-219.428571V0z" fill="#FF0000" opacity=".5" p-id="29471"></path><path d="M580.754286 265.508571V219.428571H476.891429v46.08H292.571429v46.08h472.502857v-46.08z m83.382857 399.36a19.017143 19.017143 0 0 1-17.554286 19.748572H407.405714a18.285714 18.285714 0 0 1-21.211428-16.091429V365.714286h-47.542857v299.154285a66.56 66.56 0 0 0 66.56 66.56h237.714285a66.56 66.56 0 0 0 68.022857-64.365714V365.714286h-46.811428v299.154285z" fill="#FFFFFF" p-id="29472"></path><path d="M448.365714 365.714286h42.422857v228.937143h-42.422857z m110.445715 0h42.422857v228.937143h-42.422857z" fill="#FFFFFF" p-id="29473"></path></svg>
							<svg t="1608717984834" class="icon upload_pic_success" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10299" width="40" height="40"><path d="M321.8 928.6H928V322.3z" fill="#13CE66" p-id="10300" data-spm-anchor-id="a313x.7781069.0.i21" class=""></path><path d="M685.5 844.2l-80.9-80.9c-7.4-7.4-7.4-19.5 0-27 7.4-7.4 19.5-7.4 27 0l80.9 80.9c7.4 7.4 7.4 19.5 0 27-7.5 7.4-19.7 7.4-27 0z" fill="#ffffff" p-id="10301" data-spm-anchor-id="a313x.7781069.0.i23" class="selected"></path><path d="M874.2 682.5L712.4 844.2c-7.4 7.4-19.5 7.4-27 0-7.4-7.4-7.4-19.5 0-27l161.7-161.7c7.4-7.4 19.5-7.4 27 0 7.5 7.5 7.5 19.5 0.1 27z" fill="#ffffff" p-id="10302" data-spm-anchor-id="a313x.7781069.0.i22" class="selected"></path></svg>
						</div>
					</div>
				</el-tab-pane>
			</el-tabs>
      <template #footer>
        <el-button @click="showPic = false">取 消</el-button>
        <el-button type="primary" @click="doInsertPic">确 定</el-button>
      </template>
		</el-dialog>

    <!-- 音视频上传弹窗 -->
    <el-dialog
			class="uploadMedia"
			width="700px"
			center
			v-model="showMedia"
      :title="mediaType === 1 ? '视频上传' : '音频上传'"
			:append-append-to-body="false"
			:close-on-click-modal="false"
			:close-on-press-escape="false"
			@close="doCloseMedia">
			<div class="btn_type">
				<el-radio-group v-model="mediaType" size="mini" :disabled="loading">
					<el-radio-button :label="1">视频</el-radio-button>
					<el-radio-button :label="2">音频</el-radio-button>
				</el-radio-group>
				<span v-show="dataList.length > 0" class="uploadMsg">文件已上传，如需更换请重新选择文件上传</span>
			</div>
			<div class="upload_box">
				<el-upload
					action=""
					:accept="mediaType === 1 ? 'video/*' : 'audio/*'"
					:show-file-list="false"
					:before-upload="beforeUploadMedia"
					:http-request="doUploadFileMedia">
          <div class="upload_btn">
            <svg v-show="mediaType === 1" t="1610955121499" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2764" width="75" height="75"><path d="M661.44 64H128a64 64 0 0 0-64 64v768a64 64 0 0 0 64 64h768a64 64 0 0 0 64-64V351.36L661.44 64zM1024 324.096V896a128 128 0 0 1-128 128H128a128 128 0 0 1-128-128V128a128 128 0 0 1 128-128h559.232L1024 324.096z" fill="#DFDFDF" p-id="2765"></path><path d="M352 260.096l412.352 275.648L352 811.328V260.096z m64 119.808v311.68l233.152-155.84L416 379.904zM674.752 71.04h64v189.248a32 32 0 0 0 32 32h199.04v64h-199.04a96 96 0 0 1-96-96V71.04z" fill="#DFDFDF" p-id="2766"></path><path d="M160 224m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#DFDFDF" p-id="2767"></path><path d="M160 416m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#DFDFDF" p-id="2768"></path><path d="M160 608m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#DFDFDF" p-id="2769"></path><path d="M160 800m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#DFDFDF" p-id="2770"></path><path d="M864 800m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#DFDFDF" p-id="2771"></path><path d="M864 608m-64 0a64 64 0 1 0 128 0 64 64 0 1 0-128 0Z" fill="#DFDFDF" p-id="2772"></path></svg>
            <svg v-show="mediaType === 2" t="1610955188391" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3143" width="75" height="75"><path d="M640.783996 0l319.99999 298.015991V927.359971A96.703997 96.703997 0 0 1 863.999989 1023.999968H161.504011a96.735997 96.735997 0 0 1-96.703997-96.639997V96.719997A96.735997 96.735997 0 0 1 161.504011 0z m255.999992 927.359971V369.711988H728.575993a144.175995 144.175995 0 0 1-143.999995-143.919995V64.351998L161.504011 63.999998A32.751999 32.751999 0 0 0 128.800012 96.719997V927.359971a32.703999 32.703999 0 0 0 32.703999 32.639999H863.999989a32.687999 32.687999 0 0 0 32.703999-32.671999zM648.591996 94.735997v131.055996a79.999998 79.999998 0 0 0 79.999997 79.999997H875.199989L648.591996 94.735997zM657.999995 385.599988c25.775999-7.04 46.767999 7.152 46.767999 31.519999v296.271991c0 38.399999-40.959999 74.191998-91.503997 79.999997s-91.519997-18.415999-91.519997-56.927998 40.959999-74.191998 91.519997-79.999998c34.367999-3.904 53.551998 6.528 53.551998 6.528v-145.519995c0-18.239999-20.799999-11.584-20.799999-11.584L457.488002 561.599982s-21.631999 7.36-21.632 24.432v181.087994c0 38.399999-37.055999 73.871998-87.615997 80.591998s-91.455997-16.687999-91.455997-55.071999 40.895999-75.023998 91.455997-81.871997c34.367999-4.544 49.855998 5.312 49.855999 5.312V503.839984c0-24.367999 20.927999-49.759998 46.719998-56.735998L657.999995 385.599988z" fill="#DFDFDF" p-id="3144"></path></svg>
            <el-button size="small" class="upload_media_btn" :loading="loading">
              {{loading ? '上传中，请耐心等待···' : '选择上传文件'}}
            </el-button>
          </div>
				</el-upload>
        <div v-if="dataList.length > 0">{{dataList[0].name}}</div>
			</div>
      <template #footer>
        <el-button @click="showMedia = false">取 消</el-button>
				<el-button type="primary" @click="doInsertMedia">确 定</el-button>
      </template>
		</el-dialog>
  </div>
</template>

<script setup>
  import { uploadFileApi } from '@/api/api'
  import { ref, reactive, toRefs, getCurrentInstance, onMounted } from 'vue'

  // 获取注册的全局实列
  const currentThis = getCurrentInstance().appContext.config.globalProperties

  // 定义父组件传入的值
  const props = defineProps({
    modelValue: String,
    readonly: { // 是否只读
      type: Boolean,
      default: false,
      required: false
    },
    isText: { // 是否获取纯文本
      type: Boolean,
      default: false,
      required: false
    }
  })

  // 将组件的resetData方法暴露，方便父组件可以通过ref调用
  defineExpose({destroyEditor})

  // 定义修改富内容改变，传值给父组件
  const emits = defineEmits(['update:modelValue'])

  // 获取组件定义ref为formRef实列
  const formRef = ref(null)

  const currentData = reactive({
    loading: false,
    showPic: false,
    showMedia: false,
    insertType: '2',
    mediaType: 1,
    dataList: [],
    form: {
      src: ''
    },
    rules: {
      src: [{ required: true, message: '请输入图片地址', trigger: 'blur' }]
    }
  })
  let {loading, showPic, showMedia, insertType, mediaType, dataList, form, rules} = toRefs(currentData)

  // 初始化富文本编辑器
  function initEditor() {
    tinymce.init({
      selector: '#tinymceEditor',
      inline: false, // 是否内联模式
      readonly: props.readonly,
      language: 'zh_CN',
      placeholder: '请输入内容',
      icons_url: '../../../public/tinymce/icons/custom/icons.js',
      icons: 'customIcon',
      menubar: false,
      plugins: 'formatpainter lists table link image imagetools axupimgs charmap emoticons',
      toolbar: 'emptyDocument | undo redo | fontsizeselect fontselect bold italic underline formatpainter charmap emoticons | forecolor backcolor numlist bullist | alignleft aligncenter alignright alignjustify | link table | uploadImg chooseVideo',
      toolbar_mode: 'wrap',
      width: '100%',
      min_height: 400,
      fontsize_formats: '8px 9px 10px 12px 13px 14px 15px 16px 18px 24px 32px 36px 44px',
      font_formats: '宋体=SimSun;新宋体=NSimSun;仿宋_GB2312=FangSong_GB2312;楷体_GB2312=KaiTi_GB2312;黑体=SimHei;微软雅黑=Microsoft YaHei;苹果苹方=PingFang SC;Arial=Arial;Arial Black=Arial Black;Times New Roman=Times New Roman;Courier New=Courier New;Tahoma=Tahoma;Verdana=Verdana;',
      setup: function (editor) {

        //将富文本内容传递给父组件
        editor.on('Change', function(e) {
          emits('update:modelValue', tinyMCE.editors['tinymceEditor'].getContent())
          if(props.isText) {
            emits('onGetText', tinyMCE.editors['tinymceEditor'].getContent({ format: 'text' }))
          }
        })

        // 自定义清空文档按钮
        editor.ui.registry.addButton('emptyDocument', {
          tooltip: '清空文档',
          icon: 'document-properties',
          onAction: function () {
            currentThis.$messageBox.confirm('确定清空当前文档吗?').then(() => {
              resetEditor()
              emits('update:modelValue', '')
            }).catch(() =>{
            })
          }
        })

        // 自定义上传图片按钮
        editor.ui.registry.addButton('uploadImg', {
          tooltip: '图片上传',
          icon: 'image',
          onAction: function () {
            currentData.showPic = true
          }
        })

        // 自定义音视频上传按钮
        editor.ui.registry.addButton('chooseVideo', {
          tooltip: '音视频上传',
          icon: 'media',
          onAction: function () {
            currentData.showMedia = true
          }
        })
      }
    })

    // 将父组件传入的初始值设置到富文本中
    const timer = setTimeout(() => {
      tinyMCE.editors['tinymceEditor'].setContent(props.modelValue)
      clearTimeout(timer)
    }, 300)
  }

  // 图片上传前验证格式
  function beforeUploadPic(file) {
    let isJPG = file.type === 'image/jpeg'
    let isPNG = file.type === 'image/png'
    if (!isJPG && !isPNG) {
      currentThis.$message.warning('图片必须是jpg或png格式!')
    }
    return isJPG || isPNG
  }

  // 执行图片上传
  function doUploadFilePic(e) {
    let formData = new FormData()
    formData.append('file', e.file)
    uploadFileApi(formData).then(res => {
      if(res.code === '200') {
        currentData.dataList.push({src: res.data.fullUrl})
      } else {
        currentThis.$message.error('上传失败!')
      }
    })
  }

  // 关闭图片上传弹窗
  function doClosePic() {
    // 恢复上传图片初始数据
    currentData.insertType = '2'
    currentData.dataList = []
    currentData.form.src = ''
    // 重置表单验证
    formRef.value.resetFields()
  }

  // 点击图片上传弹窗确认按钮，将图片插入富文本编辑器
  function doInsertPic() {
    if(currentData.insertType === '1') {
      formRef.value.validate((valid) => {
        if (valid) {
          tinyMCE.editors['tinymceEditor'].insertContent('<img src="' + currentData.form.src + '"width="100%" height="auto" alt=""/>')
          currentData.showPic = false
        }
      })
    } else {
      if(currentData.dataList.length > 0) {
        currentData.dataList.forEach(item => {
          tinyMCE.editors['tinymceEditor'].insertContent('<img src="' + item.src + '"width="100%" height="auto" alt=""/>')
        })
        currentData.showPic = false
      } else {
        currentThis.$message.warning('请上传图片!')
      }
    }
  }

  // 视频，音频类型上传前验证
  function beforeUploadMedia(file) {
    let isMedia = currentData.mediaType === 1 ? file.type === 'video/mp4' : file.type === 'audio/mpeg'
    if (!isMedia) {
      currentThis.$message.warning(currentData.mediaType === 1 ? '视频必须是mp4格式!' : '音频必须是mp3格式!')
    }
    return isMedia
  }

  // 执行视频，音频上传
  function doUploadFileMedia(e) {
    currentData.loading = true
    let formData = new FormData()
    formData.append('file', e.file)
    uploadFileApi(formData).then(res => {
      currentData.loading = false
      if(res.code === '200') {
        currentData.dataList.push({src: res.data.fullUrl})
      } else {
        currentThis.$message.error('上传失败!')
      }
    })
  }

  // 关闭视频，音频上传弹窗
  function doCloseMedia() {
    // 恢复上传视频，音频初始数据
    currentData.mediaType === 1 
    currentData.dataList = []
  }

  // 点击视频，音频上传弹窗确认按钮，将图片插入富文本编辑器
  function doInsertMedia() {
    if(currentData.mediaType === 1) {
      tinyMCE.editors['tinymceEditor'].insertContent('<video src="' + currentData.dataList[0].src + '" controls width="100%" height="auto" style="object-fit: fill;"></video>')
    } else {
      tinyMCE.editors['tinymceEditor'].insertContent('<audio src="' + currentData.dataList[0].src + '" controls style="width: 100%"></audio>')
    }
    currentData.showMedia = false
  }

  function destroyEditor() {
    // 销毁富文本编辑器
    tinyMCE.editors['tinymceEditor'].destroy()
  }

  function resetEditor() {
    tinyMCE.editors['tinymceEditor'].setContent('')
  }

  onMounted(() => {
    initEditor()
  })
</script>

<style lang="less" scoped>
.tinymceEditor {
  width: 100%;
  /* 图片库弹出框 */
  :deep(.uploadPic){
    overflow: hidden;
    .el-tabs{
      width: 100%;
    }
    .el-dialog__header{
      background-color: #F2F2F2 !important;
      margin-right: 0;
    }
    .el-dialog__title{
      font-weight: bold !important;
      font-size: 20px !important;
    }
    .el-dialog__headerbtn .el-dialog__close{
      font-size: 24px !important;
    }
    .el-dialog--center .el-dialog__body{
      padding: 0 !important;
    }
    .el-dialog__footer{
      padding: 10px !important;
      background-color: #F2F2F2 !important;
    }

    .upload_pic_btn_box{
      display: flex;
      justify-content: space-between;
      align-items: center;
      border-bottom: #E4E7ED solid 1px;
      padding-bottom: 15px;
      margin-bottom: 10px;
    }

    .upload_pic_btn_style{
      border-color: #00B7EE !important;
      background-color: #00B7EE !important;
      color: #ffffff !important;
    }
    .upload_pic_number{
      color: #D90615;
    }

    .upload_pic_tips_box{
      width: 100%;
      height: 200px;
      border: #E4E7ED dashed 1px;
      display: flex;
      align-items: center;
      justify-content: center;
      .upload_pic_tips{
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
      }
    }
    .upload_pic_imgs{
      width: 100%;
      min-height: 140px;
      max-height: 280px;
      overflow-x: hidden;
      overflow-y: auto;
      display: flex;
      justify-content: flex-start;
      flex-wrap: wrap;
    }
    .upload_pic_imgs>div{
      position: relative;
      width: 24%;
      height: 120px;
      margin: 0 0.5% 8px;
    }
    .upload_pic_success{
      position: absolute;
      bottom: -4px;
      right: -4px;
    }
    .upload_pic_delete{
      position: absolute;
      top: 0;
      left: 0;
      font-size: 15px;
      color: #D90615;
      cursor: pointer;
    }
  }

  /* 图片库弹出框 */
  :deep(.uploadMedia){
    overflow: hidden;
    .el-dialog__header{
			background-color: #F2F2F2 !important;
      margin-right: 0;
		}
    .el-dialog__title{
			font-weight: bold !important;
			font-size: 20px !important;
		}
    .el-dialog__headerbtn .el-dialog__close{
			font-size: 24px !important;
		}
    .el-dialog--center .el-dialog__body{
			padding: 10px 25px !important;
		}
    .el-dialog__footer{
			padding: 10px !important;
			background-color: #F2F2F2 !important;
		}
    .upload_box{
			width: 100%;
			height: 250px;
			border: #E4E7ED dashed 1px;
			margin-top: 10px;
			display: flex;
      flex-direction: column;
			align-items: center;
			justify-content: center;
      .upload_btn{
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
      }
		}
		.btn_type{
			display: flex;
			justify-content: space-between;
			align-items: center;
		}
		.uploadMsg{
			color: #f3313e;
		}
		.upload_media_btn{
			border-color: #00B7EE !important;
			background-color: #00B7EE !important;
			color: #ffffff !important;
			margin: 10px 0;
		}
  }
}
</style>